package com.tonicgb.shared.core.jwt;

import com.auth0.jwt.interfaces.Claim;
import com.tonicgb.shared.annotation.PassToken;
import com.tonicgb.shared.common.constants.Constants;
import com.tonicgb.shared.core.jwt.contracts.JWTSubject;
import com.tonicgb.shared.common.enums.MessageCodeEnum;
import com.tonicgb.shared.common.enums.UserType;
import com.tonicgb.shared.exception.ApiException;
import com.tonicgb.shared.util.JWTUtil;
import com.tonicgb.shared.util.RedisUtil;
import com.tonicgb.shared.util.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhaiyujin
 * @date 2021-09-05 23:48:07
 * @说明 Jwt token 使用类
 */
@Component
public class JWTToken {

    @Autowired
    protected RedisUtil redisUtil;

    @Value("${jwtWay}")
    protected String jwtWay;

    public  Map<String, Claim> claim;

    public Boolean check(String token,String userKeyPrefix)  {

        Object id;
        claim=JWTUtil.getClaims(token);
        id=claim.get("id").asInt();
        Integer userType=claim.get("userType").asInt();
        if(id==null||userType==null) throw new ApiException(MessageCodeEnum.UNAUTHORIZED);
        if(userType!= UserType.ADMIN.getCode()) throw new ApiException(MessageCodeEnum.JWTClaimError);

        if(jwtWay.equals("redis")){
            String redisKey=userKeyPrefix+token;
            boolean exists= redisUtil.exists(redisKey);
            if(exists){
                id=redisUtil.get(redisKey);
                redisUtil.set(redisKey,id,Constants.TOKEN_EXPRESS_MINUTES.longValue(), TimeUnit.MINUTES);
            }

            return exists;

        }else{

            JWTUtil.verifyToken(token);
        }
        Map<String, Object> hashedMap = new HashMap<>();
        hashedMap.put("id", id);
        hashedMap.put("userType",userType);
        ThreadLocalUtil.set(hashedMap);

        return true;
    }


    //获取前端传入的token
    public String getTokenFormRequest(HttpServletRequest request){
        String pathToken =request.getParameter(Constants.HEADER_AUTHORIZATION_KEY);
        if(null != pathToken){
            return pathToken;
        }
        return request.getHeader(Constants.HEADER_AUTHORIZATION_KEY);
    }


    public Boolean isPassToken(HandlerMethod handlerMethod){

        boolean pass=false;
        Method method=handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                pass= true;
            }
        }
        return pass;
    }

    public String crateToken(JWTSubject admins) throws Exception {
        String token=JWTUtil.createToken(admins); //创建token
        claim=JWTUtil.getClaims(token);//获取基本信息
        String userKeyPrefix=admins.JWTCustomClaims().getText();
        Integer id=admins.JWTIdentifier();
        if(jwtWay.equals("redis")){
            String redisKey=userKeyPrefix+token;
            redisUtil.set(redisKey,id,Constants.TOKEN_EXPRESS_MINUTES.longValue(), TimeUnit.MINUTES);
        }

        Map<String, Object> hashedMap = new HashMap<>();
        hashedMap.put("id", id);
        hashedMap.put("userType",claim.get("userType").asString());
        ThreadLocalUtil.set(hashedMap);
        return token;
    }



}
